home *** CD-ROM | disk | FTP | other *** search
- /* pe7pta.c */
- /* Include external declarations */
- #include "pe7inc.h"
-
- /*
- * g i n i t
- *
- * Get receive Initialization
- *
- */
-
- TEXT ginit(l, file)
- int l; /* Length of the filename */
- TEXT *file; /* File name pointer */
- {
- int len, num, slen; /* Packet length, number */
-
- if (numtry++ > MAXTRY) return ('A'); /* If too many tries, "abort" */
- flushinput(); /* Clear out the i/o channel */
-
- spack('R',n,l,file); /* Send the requested file name */
- switch(rpack(&len,&num,recpkt)) /* Get a packet */
- {
- case 'S': /* Send-Init packet */
- if ( n != num)
- {
- case 'N':
- case FALSE:
- nxi++;
- return (state);
- }
- if (!rpar(recpkt,&len)) /* Get the other side's init data */
- return ('A'); /* error with the packet parameters */
- slen = spar(packet0); /* Fill up packet with my init info */
- spack('Y',n,slen,packet0);/* ACK with my parameters */
- oldtry = numtry; /* Save old try count */
- nxtpkt();
- return ('F'); /* Enter File-Receive state */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Some other packet type, "abort" */
- }
- }
-
- /*
- * x i n i t
- *
- * Server command scanning
- */
-
- TEXT xinit()
- {
- int i, /* A counter */
- search, /* Filename search state flag */
- len, num, slen; /* Packet length, number */
- TEXT *filep; /* Pointer to input buffer */
-
- switch(rpack(&len,&num,recpkt)) /* Get a packet */
- {
- case 'S': /* Send-Init packet */
- if (!rpar(recpkt,&len)) /* Get the other side's init data */
- return ('A'); /* error with the packet parameters */
- slen = spar(packet0); /* Fill up packet with my init info */
- spack('Y',n,slen,packet0); /* ACK with my parameters */
- oldtry = numtry; /* Save old try count */
- nxtpkt();
- return ('F'); /* Enter File-Receive state */
-
- case 'I': /* Send-Init packet */
- if (!rpar(recpkt,&len)) /* Get the other side's init data */
- return ('A'); /* error with the packet parameters */
- slen = spar(packet0); /* Fill up packet with my init info */
- spack('Y',n,slen,packet0); /* ACK with my parameters */
- oldtry = numtry; /* Save old try count */
- n = 0;
- numtry = 0;
- return (state); /* Say we got our parameters */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return ('A'); /* abort */
-
- case FALSE: /* Didn't get packet */
- nxi++;
- spack('N',n,0,0); /* Return a NAK */
- case 'N':
- return (state); /* Keep trying */
-
- case 'R':
- /* copy the packet data into a filename_buffer */
- /* cpystr(&filename_buffer, &recpkt, NULL); /* */
- btobemp(filename_buffer, recpkt, MAXPACKSIZ); /* Uncode packet */
- filecount = 0;
- filelist = &files;
- filep = &filename_buffer;
- search = 2;
- while (*filep != NULL && filecount < 10)
- {
- switch (search)
- {
- case 1: /* Looking for next filename */
- if (iswhite(*filep))
- break;
- search = 2;
- case 2: /* Looking for filename */
- if (iswhite(*filep))
- break;
- files[filecount++] = filep;
- search = 3;
- case 3: /* Looking for end of filename */
- if (!iswhite(*filep))
- break;
- *filep = NULL;
- search = 1;
- }
- filep++;
- }
- if (debug) printf("Xinit 1: Request for %d files...\n", filecount);
- if (gnxtfl() == FALSE) /* Any files to send? */
- return ('B'); /* if not, break, EOT, all done */
- return ('S'); /* Start sending files, switch state to S */
- case 'G':
- if (recpkt[0] == 'F')
- {
- spack('Y',n,0,0); /* say ok */
- return ('G');
- }
- else
- {
- error("Invalid server command");
- return (state); /* keep trying */
- }
- default:
- error("Unknown packet type");
- return (state);
- }
- }
-
- /*
- * s f i l e
- *
- * Send File Header.
- */
-
- TEXT sfile()
- {
- TEXT filnam1[MAXFNAME], /* Converted file name */
- *newfilnam, /* Pointer to file name to send */
- *cp; /* char pointer */
- int num, len; /* Packet number, length */
- ULONG time();
-
- if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */
-
- if (fd == NULL) /* If not already open, */
- {
- if (debug) printf("Sfile 1: Opening %s for sending.\n",filnam);
- /* Open file to be sent */
- if ((fd = fopen(&pfio, filnam, READ)) == NULL)
- /* If bad file pointer, give up */
- {
- printmsg("Cannot open file %s\n",filnam);
- return ('A');
- }
-
- /* cpystr(filnam1, filnam, NULL); /* Copy file name */
- btobemp(filnam1, filnam, MAXFNAME); /* Copy file name */
- newfilnam = cp = filnam1;
- while (*cp != '\0') /* Strip off all leading directory */
- if (*cp++ == '/') /* names (ie. up to the last /). */
- newfilnam = cp;
-
- if (filnamcnv) /* Convert lower case to upper */
- for (cp = newfilnam; *cp != '\0'; cp++)
- *cp = toupper(*cp);
-
- len = cp - newfilnam; /* Compute length of new filename */
-
- if (vflg)
- printmsg("Sending %s as %s",filnam,newfilnam);
- }
- dostat(2);
- spack('F',n,len,newfilnam); /* Send an F packet */
- switch(rpack(&len,&num,recpkt)) /* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num<0 ? 63 : num);/* unless it's NAK for next packet */
- case 'Y':
- if (n != num) /* which is just like an ACK for */
- { /* Wrong packet number */
- case FALSE: /* Receive failure, stay in F state */
- nxi++;
- return (state);
- }
- nxtpkt();
- dostat(4);
- repeat_count = 0; /* Reset repeat character counter */
- empty[1-pknum] = 0; /* Make other buffer empty */
- if ((empty[pknum] = size[pknum] = bufill (packet[pknum])) != EOF)
- return ('E'); /* Switch to data state */
- return ('Z'); /* Must be end of file */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Something else, just "abort" */
- }
- }
-
- /*
- * r f i l e
- *
- * Receive File Header
- */
-
- TEXT rfile()
- {
- TEXT filnam1[MAXFNAME]; /* Holds the converted file name */
- int num, len, slen; /* Packet number, length */
- int dum; /* Holds array pointer */
- ULONG time();
-
- if (numtry++ > MAXTRY) return ('A'); /* "abort" if too many tries */
- dostat(2);
- switch(rpack(&len,&num,recpkt)) /* Get a packet */
- {
- case 'S': /* Send-Init, maybe our ACK lost */
- if (oldtry++ > MAXTRY) return ('A'); /* If too many tries "abort" */
- if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
- {
- /* Yes, ACK it again with */
- slen = spar(packet0);/* our Send-Init parameters */
- spack('Y',num,slen,packet0);
- numtry = 0; /* Reset try counter */
- return (state); /* Stay in this state */
- }
- else return ('A'); /* Not previous packet, "abort" */
-
- case 'Z': /* End-Of-File */
- if (oldtry++ > MAXTRY) return ('A');
- if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
- {
- /* Yes, ACK it again. */
- spack('Y',num,0,0);
- numtry = 0;
- return (state); /* Stay in this state */
- }
- else return ('A'); /* Not previous packet, "abort" */
-
- case 'F': /* File Header (just what we want) */
- if (num != n) return ('A');/* The packet number must be right */
- /* cpystr(filnam1, recpkt, NULL); /* Copy the file name */
- btobemp(filnam1, recpkt, MAXFNAME); /* Copy the file name */
-
- if (filnamcnv) /* Convert upper case to lower */
- for (filnam=filnam1; *filnam != '\0'; filnam++)
- *filnam = tolower(*filnam);
-
- /* Create the file for writing into */
- if ((fd = fcreate(&pfio, filnam1, WRITE)) == NULL)
- {
- error("Cannot create %s",filnam1); /* Give up if can't */
- return ('A');
- }
- if (vflg)
- printmsg("Receiving %s as %s",recpkt,filnam1);
- spack('Y',n,0,0); /* Acknowledge the file header */
- oldtry = numtry; /* Reset try counters */
- nxtpkt();
- dostat(4);
- return ('D'); /* Switch to Data state */
-
- case 'B': /* Break transmission (EOT) */
- if (num != n) return ('A'); /* Need right packet number here */
- spack('Y',n,0,0); /* Say OK */
- return ('C'); /* Go to complete state */
-
- case FALSE: /* Didn't get packet */
- nxi++;
- spack('N',n,0,0); /* Return a NAK */
- return (state); /* Keep trying */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Some other packet, "abort" */
- }
- }
-
- /*
- * Checksum computations
- *
- * chk1 - Compute a type 1 Kermit 6 bit checksum
- * chk2 - Compute a type 2 Kermit block check
- * chk3 - Compute a type 3 Kermit block check
- *
- */
- chk1(packet)
- char *packet;
- {
- int checksum;
- checksum = chk2(packet);
- return ((((checksum & 0300) >> 6) + checksum) & 077);
- }
-
- chk2(packet)
- char *packet;
- {
- ULONG checksum;
-
- for (checksum = 0; *packet != '\0' ; packet++)
- checksum += pflg ? *packet & 0177 : *packet;
- return (checksum);
- }
-
- chk3(packet)
- char *packet;
- {
- int c, checksum, q;
-
- checksum = 0;
- while ((c = pflg ? *packet & 0177 : *packet) != '\0')
- {
- q = (checksum ^ c) & 017; /* Low order nibble */
- checksum = (checksum >> 4) ^ (q * 010201);
- q = (checksum ^ (c >> 4)) & 017; /* High order nibble */
- checksum = (checksum >> 4) ^ (q * 010201);
- packet++;
- }
- return (checksum);
- }
-
- /*
- * s p a r
- *
- * Fill the data array with my send-init parameters
- *
- */
-
- spar(data)
- TEXT data[];
- {
- int len;
- data[0] = tochar(MAXPACKSIZ);/* Biggest packet I can receive */
- data[1] = tochar(MYTIME); /* When I want to be timed out */
- data[2] = tochar(MYPAD); /* How much padding I need */
- data[3] = ctl(MYPCHAR); /* Padding character I want */
- data[4] = tochar(MYEOL); /* End-Of-Line character I want */
- data[5] = MYQUOTE; /* Control-Quote character I send */
- if (state == 'S')
- {
- /* Set up the startup parameters */
- /* The other side may call the shots if we are a server */
- data[6] = sqbin = image ? pflg ? MYQBIN : DEFQBIN : 'N';
- data[7] = DEFCHKT; /* I will use this check sum */
- data[8] = DEFREPT; /* This is my repeat character */
- data[9] = tochar(NULL); /* No bit mask at this time */
- data[10] = tochar(NULL);
- data[11] = tochar(NULL);
- data[12] = tochar(NULL);
- data[13] = tochar(NULL);
- /* Tell the other side what we set up in the start */
- data[14] = image ? tochar( 1 ) : tochar ( NULL );
- data[15] = pflg ? pflg : tochar(NULL);
- len = 16;
- }
- else /* Receive flag must be on. We are not the starters */
- {
- data[6] = rqbin; /* Quote character both sides will use */
- data[7] = chkt; /* Checksum type */
- data[8] = rrept; /* Set My repeat character */
- data[9] = tochar(NULL); /* No bit mask at this time */
- len = 10;
- }
- if (debug > 1)
- {
- printf("Spar: spsiz=%d, timint=%d\n", spsiz, timint);
- printf(" pad=%d, padchar=%d, eol=%d, ", pad, padchar, eol);
- printf("quote=%d, qbin=%d, chkt=%d, ", quote, qbin, chkt);
- printf("rept=%d\n", rept);
- if (len > 10)
- printf(" image= %d, pflg= %c, iflg= %d, spflg= %c\n",
- image,pflg,iflg,spflg);
- }
- return ( len );
- }
-
- /* r p a r
- *
- * Get the other host's send-init parameters
- *
- */
-
- rpar(data,len)
- TEXT data[];
- int *len;
- {
- TEXT chkchar();
-
- /* Maximum send packet size */
- spsiz = *len < 1 ? DEFPACKSIZ : unchar(data[0]);
-
- /* When I should time out */
- timint = *len < 2 ? MYTIME : unchar(data[1]);
-
- /* Number of pads to send */
- pad = *len < 3 ? 0 : unchar(data[2]);
-
- /* Padding character to send */
- padchar = dopar(*len < 4 ? NULL : ctl(data[3]));
-
- /* EOL character I must send */
- eol = *len < 5 ? CR : unchar(data[4]);
-
- /* Incoming data quote character */
- quote = *len < 6 ? '#' : data[5];
-
- /* Force to a type one check sum */
- chkt = *len < 8 ? DEFCHKT : data[7] != MYCHKT ? DEFCHKT : MYCHKT;
-
- /* Set up the multi repeat char */
- rrept = *len < 9 ? ' ' : data[8];
-
- if (state != 'S')
- {
- /* Determine the state of image and parity flags from the other side */
- image = *len < 15 ? iflg : data[14] == SP ? FALSE : TRUE;
- pflg = *len < 16 ? spflg : data[15] == SP ? FALSE : data[15];
-
- /* Determine the state of the sqbin */
- sqbin = image ? pflg ? MYQBIN : DEFQBIN : 'N';
-
- /* Determine the quoting mode we will use based on what the other side
- * allows and what we are capable of */
- rqbin = *len < 7 ? 'N' : data[6] == DEFQBIN ? sqbin : data[6];
- qbin = chkchar(rqbin);
-
- /* Determine the repeat mode based on what the other side allows */
- rept = chkchar(rrept);
-
- }
- else
- {
- /* Determine the final quoting mode based on what the other side allows */
- rqbin = *len < 7 ? 'N' : data[6];
- qbin = sqbin == DEFQBIN ?
- chkchar(rqbin) : rqbin == MYQBIN ? MYQBIN : FALSE;
-
- /* Determine the final repeat mode based on what the other side allows */
- rept = rrept == DEFREPT ? rrept : FALSE;
- }
-
- /* Force 8 bit quoting if requested and we are not generating parity */
- if (qbin && !pflg)
- pflg = 'n';
- /* Maybe we can not do image because the other end can
- not support binary quote */
- if (image && rqbin == 'N')
- {
- error("Binary file transfer not supported");
- return (FALSE);
- }
-
- if (debug > 1)
- {
- printf("Rpar: spsiz=%d, timint=%d\n", spsiz, timint);
- printf(" pad=%d, padchar=%d, eol=%d, ", pad, padchar, eol);
- printf("quote=%d, qbin=%d, chkt=%d, ", quote, qbin, chkt);
- printf("rept=%d\n", rept);
- if (*len > 14 )
- printf(" image=%d, pflg=%c\n",image,pflg);
- }
- return (TRUE);
- }
-
- /*
- * b u f i l l
- *
- * Get a bufferful of data from the file that's being sent.
- *
- */
-
- bufill(buffer)
- TEXT buffer[]; /* Buffer */
- {
- int i; /* Loop index */
- METACH t; /* Character that may be output */
- static METACH tt {0}; /* For the comparisions of the repeat count */
-
- i = 0; /* Init data buffer pointer */
-
- while ((t = getc(&pfio)) != EOF) /* fetch till end */
- {
- file.fc++;
- if (rept) /* If rept set then true */
- {
- if (repeat_count) /* If r..c.. set then true */
- {
- /* Check for repeat character and not too many of them */
- if ((tt == t) && (++repeat_count < 95))
- continue;
- /* The characters were different or we ran out of
- repeat count */
- if (repeat_count > 3) /* Output repeat string */
- {
- buffer[i++] = rept;
- if (repeat_count >= 95) repeat_count = 94;
- buffer[i++] = tochar(repeat_count);
- repeat_count = 1; /* Set for next */
- }
- for (; repeat_count ; repeat_count -= 1)
- store_in_buffer(tt, buffer, &i);
- /* We have output the repeat count and the repeat character */
- }
- /* End of repeat_count test */
- tt = t; /* Set up temps for next character */
- repeat_count = 1;
- }
- /* End of non NULL rept */
- else /* rept = 0 */
- store_in_buffer(t, buffer, &i);
-
- if (i >= spsiz-SPOVER) return (i); /* Check length */
- }
- /* End of while loop */
- /* Test if there is an repeat count outstanding.
- It could be that we have not inserted any data into
- output buffer */
- if (repeat_count > 3)
- {
- buffer[i++] = rept;
- buffer[i++] = tochar(repeat_count);
- repeat_count = 1; /* Set for next */
- }
- for (; repeat_count ; --repeat_count)
- store_in_buffer(tt, buffer, &i);
-
- if (i==0) return (EOF); /* Wind up here only on EOF */
- /* We need to split the packet. Scan backwards for a natural
- * break, and then send of the packet. When we return point
- * to the data and move to the front the rest and fetch more
- * more data. */
- /* Natural breaks are the quote character, repeat character
- * and the binary character */
- return (i); /* Handle partial buffer */
- }
-
- /*
- * b u f e m p
- *
- * Put data from an incoming packet into a file.
- *
- */
-
- bufemp(buffer,len)
- register TEXT buffer[]; /* Buffer */
- int len; /* Length */
- {
- register int i; /* Counter for number of characters */
- int ri; /* Repeat counter for repeated characters */
- TEXT t, t7, tm; /* Character holders */
-
- for (i = 0; i < len; i++) /* Loop thru the data field */
- {
- tm = 0; /* Preset for next */
- t = buffer[i]; /* Get character */
- ri = 1; /* Set repeat count to one (do at least one) */
- /* At this point we check for a repeat character
- * if the rept char is set then the condition will be tested
- * else we can not get here since the character t may
- * not be a NULL */
- if (t == rept) /* Repeated character? */
- {
- ri = unchar(buffer[++i]); /* Fetch repeat count */
- t = buffer[++i]; /* Fetch next character */
- }
- if (t == qbin) /* Next character have high bit on? */
- {
- tm = 0200; /* Set mask to high bit on */
- t = buffer[++i];/* Fetch next character */
- }
- if (t == quote) /* Control quote? */
- {
- /* Yes */
- t = buffer[++i]; /* Get the quoted character */
- t7 = t & 0177; /* make a match character */
- if (t7 != quote && t7 != rept && t7 != qbin) /* Low bits
- match quote, rept or qbin? */
- t = ctl(t); /* No, uncontrollify it */
- }
- if (t==CR && !image) /* Pass CR if in image mode */
- continue;
-
- t |= tm;
- for (; ri ; --ri) /* We put at least one character away */
- {
- putc(&pfio, t);
- file.fc++;
- }
- }
- }
-
- /*
- * b t o b e m p
- *
- * Put data from an incoming packet into a buffer.
- *
- */
-
- btobemp(bout,buffer,len)
- register TEXT buffer[]; /* Buffer */
- register TEXT bout[]; /* Output Buffer */
- int len; /* Length */
- {
- register int i; /* Counter for number of characters */
- register int j; /* Output buffer counter */
- int ri; /* Repeat counter for repeated characters */
- TEXT t, t7, tm; /* Character holders */
-
- j = 0; /* Initialize output buffer pointer */
- if(debug) printf("[btobemp] buffer=>>>%s<<<\n",buffer);
- /* for (i = 0; i < len; i++) /* Loop thru the data field */
- for (i = 0; buffer[i] != '\0'; i++) /* Loop thru the data field */
- {
- tm = 0; /* Preset for next */
- t = buffer[i]; /* Get character */
- ri = 1; /* Set repeat count to one (do at least one) */
- /* At this point we check for a repeat character
- * if the rept char is set then the condition will be tested
- * else we can not get here since the character t may
- * not be a NULL */
- if (t == rept) /* Repeated character? */
- {
- ri = unchar(buffer[++i]); /* Fetch repeat count */
- t = buffer[++i]; /* Fetch next character */
- }
- if (t == qbin) /* Next character have high bit on? */
- {
- tm = 0200; /* Set mask to high bit on */
- t = buffer[++i];/* Fetch next character */
- }
- if (t == quote) /* Control quote? */
- {
- /* Yes */
- t = buffer[++i]; /* Get the quoted character */
- t7 = t & 0177; /* make a match character */
- if (t7 != quote && t7 != rept && t7 != qbin) /* Low bits
- match quote, rept or qbin? */
- t = ctl(t); /* No, uncontrollify it */
- }
- if (t==CR && !image) /* Pass CR if in image mode */
- continue;
-
- t |= tm;
- for (; ri ; --ri) /* We put at least one character away */
- {
- if( j >= (len) ) {
- printf("Kermit: [btobemp] Expanded packet overflows buffer\
- \n j=%d MAXFNAME=%d\n",j,(MAXFNAME));
- error("Kermit: [btobemp] Expanded packet overflows buffer\n");
- break;
- }
- bout[j] = t;
- j++;
- }
- }
- if( j < len )
- bout[j] = '\0';
- }
-
- /*
- * s t o r e _ i n _ b u f f e r
- *
- * This routine stores the character into the output buffer
- *
- */
-
- store_in_buffer(t, buffer, i)
- TEXT t;
- register TEXT buffer[];
- register int *i;
- {
- TEXT t7,tm;
-
- t7 = t & 0177; /* Strip high bit */
-
- if (t7 == '\n' && !image)
- {
- /* Do LF->CRLF mapping if !image */
- buffer[(*i)++] = MYQUOTE;
- buffer[(*i)++] = ctl('\r');
- }
- if (qbin != 0 && (pflg ? t & 0200 : 0) != 0) /* Binary quote on? */
- buffer[(*i)++] = MYQBIN; /* Output a flag char */
-
- /* Does this character need special handling? */
- if (t7 < SP || t7 == DEL)
- {
- /* Yes this character need some changes */
- buffer[(*i)++] = MYQUOTE; /* Quote the character */
- t7 = ctl(t7); /* and uncontrolify */
- t = ctl(t);
- }
- else /* it is not a special character */
- {
- if (t7 == MYQUOTE || t7 == rept || t7 == qbin)
- buffer[(*i)++] = MYQUOTE; /* Quote the character */
- }
-
- buffer[(*i)++] = pflg ? t7 : t;
- }
- /* pe7pta.c End-of-file */
-